/*
 * StanzaReader.java
 *
 * Created on August 21, 2007, 2:17 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package org.xeerkat.xmpp;

import java.net.URI;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.infoset.xml.Element;
import org.infoset.xml.Item;
import org.infoset.xml.ItemDestination;
import org.infoset.xml.ItemSource;
import org.infoset.xml.Name;
import org.infoset.xml.Named;
import org.infoset.xml.XMLException;

/**
 *
 * @author alex
 */
public class StanzaReader
{

   public final static Name TO_PROPERTY = Name.create("to");
   public final static Name FROM_PROPERTY = Name.create("from");
   public final static Name ID_PROPERTY = Name.create("id");
   public final static Name VERSION_PROPERTY = Name.create("version");

   Map<Name,String> properties;
   Logger log;
   ItemSource source;
   boolean running;
   long lastReceivedAt = 0;
   /** Creates a new instance of StanzaReader */
   public StanzaReader(Logger log,ItemSource source)
   {
      this.log = log;
      this.source = source;
      this.running = false;
   }
   
   public ItemSource getItemSource() {
      return source;
   }
   
   public void start() 
      throws XMLException
   {
      properties = new TreeMap<Name,String>();
      Item item = source.receive(); // the document

      while ((item=source.receive()).getType()!=Item.ItemType.ElementItem);
      Element e = (Element)item;
      if (!e.getName().equals(Protocol.STREAM)) {
         throw new XMLException("Unrecognized start element: "+e.getName());
      }
      log.fine("Stream started:");
      boolean fineLog = log.isLoggable(Level.FINE);
      for (Name name : e.getAttributes().keySet()) {
         String value = e.getAttributeValue(name);
         if (fineLog) {
            log.info(name+": "+value);
         }
         properties.put(name,value);
      }
      running = true;
   }
   
   public boolean next(ItemDestination dest)
      throws XMLException
   {
      if (!running) {
         return false;
      }
      int level = 0;
      Item item;
      while ((item=source.receive())!=null) {
         //log.info(item.toString());
         if (level==0 && item.getType()==Item.ItemType.ElementEndItem && ((Named)item).getName().equals(Protocol.STREAM)) {
            running = false;
            return false;
         }
         if (level==0 && item.getType()!=Item.ItemType.ElementItem) {
            continue;
         }
         try {
            if (dest!=null) {
               dest.send(item);
            }
         } catch (Exception ex) {
            log.log(Level.SEVERE,"Exception while processing stanza.",ex);
         }
         switch (item.getType()) {
            case ElementItem:
               level++;
               break;
            case ElementEndItem:
               level--;
               break;
         }
         if (level==0) {
            lastReceivedAt = System.currentTimeMillis();
            return true;
         }
      }
      return false;
   }
   
   public Map<Name,String> getProperties() {
      return properties;
   }
   
   public long getLastReceivedAt() {
      return lastReceivedAt;
   }
   
}
